#include "stdafx.h"
#include "Link.h"
#include "Http.h"

#pragma comment(lib,"Winhttp.lib")

Http::Http(String* host,PTSTR agent){
	session=WinHttpOpen(agent,WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0);
	if(session){
		Http* p=this;
		WinHttpSetOption(session,WINHTTP_OPTION_CONTEXT_VALUE,&p,sizeof(p));
		WinHttpSetStatusCallback(session,callback,
			WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,NULL);
		connect=WinHttpConnect(session,host->Ptstr(),
			INTERNET_DEFAULT_HTTP_PORT,0);
		if(connect)
			return;
	}
	throw(0);
}
Http::~Http(void){
	if(connect)
		WinHttpCloseHandle(connect);
	if(session)
		WinHttpCloseHandle(session);
}

void CALLBACK Http::callback(HINTERNET session,DWORD_PTR context,DWORD status,
	LPVOID info,DWORD length){
	Http* p=(Http*)context;
	if(p)
		p->onCallback(session,status,info,length);
}
Bin* Http::get(HINTERNET req){
	BOOL r=WinHttpSendRequest(req,WINHTTP_NO_ADDITIONAL_HEADERS,0,
		WINHTTP_NO_REQUEST_DATA,0,0,0);
	if(r){
		r=WinHttpReceiveResponse(req,NULL);
		if(r){
			uint len=0;
			Link *link=new Link();
			do{
				if(WinHttpQueryDataAvailable(req,&len)&&len){
					if(void *buf=malloc(len)){
						uint ded;
						if(WinHttpReadData(req,buf,len,&ded))
							link->append(buf,ded);
						free(buf);
					}
				}
			}while(len>0);
			uint n=link->comp(0);
			ubyte *d=(ubyte*)malloc(n);
			if(d){
				link->comp(d);
				WinHttpCloseHandle(req);
				return new Bin(d,n);
			}
		}
	}
	throw(0);
}
Bin* Http::get(PTSTR location){
	HINTERNET req=WinHttpOpenRequest(connect,L"GET",location,NULL,
		WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,0);
	if(!req)
		throw(0);
	Bin* ret=get(req);
	WinHttpCloseHandle(req);
	return ret;
}
void Http::onCallback(HINTERNET inernet,uint status,LPVOID info,uint length){
}
uint Http::status(HINTERNET req){
	uint len=0;
	WinHttpQueryHeaders(req,WINHTTP_QUERY_STATUS_CODE,
		WINHTTP_HEADER_NAME_BY_INDEX,NULL,&len,WINHTTP_NO_HEADER_INDEX);
	if(len){
		if(PTSTR s=(TCHAR*)malloc(len)){
			WinHttpQueryHeaders(req,WINHTTP_QUERY_STATUS_CODE,
				WINHTTP_HEADER_NAME_BY_INDEX,s,&len,
				WINHTTP_NO_HEADER_INDEX);
			uint res;
			swscanf_s(s,L"%d",&res);
			free(s);
			return res;
		}
	}
	return 0;
}
void Http::put(PTSTR location,PSTR contents){
	HINTERNET req=WinHttpOpenRequest(connect,L"PUT",location,NULL,
		WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,0);
	if(req){
		BOOL r=0;
		if(contents){
			uint n=strlen(contents);
			r=WinHttpSendRequest(req,WINHTTP_NO_ADDITIONAL_HEADERS,0,
				contents,n,n,0);
		}else r=WinHttpSendRequest(req,WINHTTP_NO_ADDITIONAL_HEADERS,0,
			WINHTTP_NO_REQUEST_DATA,0,0,0);
		if(r)
			r=WinHttpReceiveResponse(req,NULL);
		WinHttpCloseHandle(req);
	}
}